package controllers

import (
	"fmt"
	"net/http"
	"os"
	"strconv"
	"strings"

	response "yuanaiproblem/models"
	"yuanaiproblem/models/dto"
	"yuanaiproblem/services"
	"yuanaiproblem/utils"

	"github.com/gin-gonic/gin"
)

// AdminCreateUser 管理员创建用户
// 入参：用户名、密码；返回：创建的用户信息或错误
// 流程：验证参数 -> 调用服务创建用户 -> 返回结果
func AdminCreateUser(c *gin.Context) {
	// 初始化并绑定注册请求参数
	var req dto.RegisterRequest
	if err := c.ShouldBind(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误: "+err.Error())
		return
	}
	// 调用服务层services创建用户
	user, err := services.CreateUser(req.Username, req.Password)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}
	// 返回统一成功响应
	response.Success(c, user, "创建用户成功")
}

// DeleteUser 管理员删除用户（控制器）
// 入参：用户ID；返回：删除结果或错误
// 流程：解析用户ID -> 调用服务删除用户 -> 处理错误并返回结果
func DeleteUser(c *gin.Context) {
	// 解析路径参数中的用户ID
	userID, err := strconv.ParseInt(c.Param("id"), 10, 32)
	if err != nil {
		response.Error(c, http.StatusBadRequest, "用户ID格式错误")
		return
	}
	// 调用服务层执行删除操作
	if err := services.DeleteUser(int32(userID)); err != nil {
		// 根据错误类型返回对应状态码
		switch err.Error() {
		case "用户不存在":
			response.Error(c, http.StatusNotFound, err.Error())
		case "禁止删除管理员用户":
			response.Error(c, http.StatusForbidden, err.Error())
		default:
			response.Error(c, http.StatusInternalServerError, err.Error())
		}
		return
	}
	// 返回删除成功响应-包含被删除用户ID
	response.Success(c, userID, "用户已删除")
}

// AdminGetAllQuestions 管理员查询所有题目
// 入参：分页参数-页码、页大小；返回：分页题目列表或错误
// 流程：解析分页参数 -> 调用服务查询 -> 返回结果
func AdminGetAllQuestions(c *gin.Context) {
	// 解析查询参数中的分页信息
	var req dto.QuestionPageQuery
	if err := c.ShouldBindQuery(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数格式错误")
		return
	}
	// 调用服务层查询所有题目
	result, err := services.GetAllQuestionsByAdmin(req.Page, req.PageSize)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, "查询失败: "+err.Error())
		return
	}
	// 返回查询结果
	response.Success(c, result, "查询成功")
}

// AdminGetQuestionByID 管理员查询单个题目
// 入参：题目ID；返回：单个题目详情或错误
// 流程：解析题目ID -> 调用服务查询 -> 返回结果
func AdminGetQuestionByID(c *gin.Context) {
	// 解析路径参数中的题目ID
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		response.Error(c, http.StatusBadRequest, "ID格式错误")
		return
	}
	// 调用服务层查询指定ID的题目
	question, err := services.GetQuestionsByID(id)
	if err != nil {
		response.Error(c, http.StatusNotFound, "题目不存在")
		return
	}
	// 返回查询到的题目详情
	response.Success(c, question)
}

// AdminGetAllPapers 管理员查询所有试卷
// 入参：分页参数（页码、页大小）；返回：试卷列表或错误
// 流程：解析分页参数 -> 调用服务查询 -> 返回结果
func AdminGetAllPapers(c *gin.Context) {
	// 解析查询参数中的分页信息
	var query dto.PaperPageQuery
	if err := c.ShouldBindQuery(&query); err != nil {
		response.Error(c, http.StatusBadRequest, "参数格式错误: "+err.Error())
		return
	}
	// 调用服务层查询所有试卷（带分页）
	papers, _, err := services.AdminGetAllPaper(query.Page, query.PageSize)
	if err != nil {
		response.Error(c, http.StatusInternalServerError, err.Error())
		return
	}
	// 返回查询结果
	response.Success(c, papers, "查询所有试卷成功")
}

// AdminGetPaperByID 管理员根据ID查询试卷
// 入参：试卷ID；返回：单个试卷详情或错误
// 流程：解析试卷ID -> 调用服务查询 -> 处理错误并返回结果
func AdminGetPaperByID(c *gin.Context) {
	// 解析路径参数中的试卷ID
	paperId, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		response.Error(c, http.StatusBadRequest, "试卷ID格式错误")
		return
	}
	// 调用服务层查询指定ID的试卷
	paper, err := services.AdminGetPaperByID(paperId)
	if err != nil {
		// 根据错误类型返回对应状态码
		if err.Error() == "试卷不存在" {
			response.Error(c, http.StatusNotFound, err.Error())
		} else {
			response.Error(c, http.StatusInternalServerError, err.Error())
		}
		return
	}
	// 返回查询到的试卷详情
	response.Success(c, paper, "成功根据id查询试卷")
}

// GetUserStats 获取用户维度统计
// 入参：用户ID；返回：用户统计数据或错误
// 流程：解析用户ID -> 调用服务查询统计 -> 返回结果
func GetUserStats(ctx *gin.Context) {
	// 获取路径参数中的用户ID-通过param
	userID := ctx.Param("id")
	// 调用服务层查询用户相关统计数据
	userStats, err := services.GetUserStats(userID)
	if err != nil {
		response.Error(ctx, http.StatusNotFound, err.Error())
		return
	}
	// 返回用户统计数据
	response.Success(ctx, userStats, "用户统计数据获取成功")
}

// GetSystemStats 获取系统维度统计
// 入参：无；返回：系统统计数据
// 流程：调用服务查询系统统计 -> 返回结果
func GetSystemStats(ctx *gin.Context) {
	// 调用服务层获取系统维度统计数据
	systemStats, err := services.GetSystemStats()
	if err != nil {
		response.Error(ctx, http.StatusNotFound, err.Error())
		return
	}
	// 返回系统统计数据
	response.Success(ctx, systemStats, "系统统计数据获取成功")
}

// GetSupportedModels 获取系统支持的所有AI模型
// 从环境变量SUPPORTED_AI_MODELS读取，格式为逗号分隔字符串(如"doubao,tongyi")
// 若环境变量未配置，默认支持doubao和tongyi
func GetSupportedModels(c *gin.Context) {
	// 从环境变量读取配置
	modelsStr := os.Getenv("SUPPORTED_AI_MODELS")
	// 处理空值情况-设置默认支持的模型
	if modelsStr == "" {
		modelsStr = "doubao,tongyi"
	}
	// 分割字符串并去重（使用map过滤重复项）
	modelSet := make(map[string]struct{})
	for _, model := range strings.Split(modelsStr, ",") {
		model = strings.TrimSpace(model) // 去除空格
		if model != "" {
			modelSet[model] = struct{}{}
		}
	}
	// 转换为切片返回
	supportedModels := make([]string, 0, len(modelSet))
	for model := range modelSet {
		supportedModels = append(supportedModels, model)
	}

	response.Success(c, supportedModels, "获取支持的模型列表成功")
}

// GetAIConfig 获取指定AI模型的详细配置
// 参数model：模型标识（如doubao/tongyi）
// 从环境变量读取该模型的所有配置项（如API_KEY、BASE_URL等）
func GetAIConfig(c *gin.Context) {
	model := c.Query("model")
	// 校验模型是否支持
	if !utils.IsModelSupported(model) {
		modelsStr := os.Getenv("SUPPORTED_AI_MODELS")
		if modelsStr == "" {
			modelsStr = "doubao,tongyi"
		}
		response.Error(c, http.StatusBadRequest,
			fmt.Sprintf("不支持的AI模型，支持的模型：%s", modelsStr))
		return
	}
	// 通用方式读取配置
	config := dto.AIConfigResponse{
		Model:       model,
		APIKey:      os.Getenv(model + "_API_KEY"),                         // 如doubao_API_KEY
		BaseURL:     os.Getenv(model + "_BASE_URL"),                        // 如doubao_BASE_URL
		ModelName:   os.Getenv(model + "_MODEL"),                           // 如doubao_MODEL
		Temperature: float32(utils.GetEnvFloat(model+"_TEMPERATURE", 0.7)), // 带默认值的浮点型配置
		MaxTokens:   utils.GetEnvInt(model+"_MAX_TOKENS", 2000),            // 带默认值的整型配置
		Timeout:     utils.GetEnvInt(model+"_TIMEOUT", 30),                 // 超时时间配置
	}
	response.Success(c, config, "获取配置成功")
}

// UpdateAIConfig 更新指定AI模型的配置
// 参数model：模型标识（如doubao/tongyi）
// 仅更新请求体中非空的字段，空字段不修改原配置
func UpdateAIConfig(c *gin.Context) {
	model := strings.TrimSpace(c.Query("model"))
	if model == "" {
		response.Error(c, http.StatusBadRequest, "模型名称不能为空")
		return
	}
	// 检查模型是否支持
	if !utils.IsModelSupported(model) {
		supportedStr := os.Getenv("SUPPORTED_AI_MODELS")
		if supportedStr == "" {
			supportedStr = "doubao,tongyi"
		}
		response.Error(c, http.StatusBadRequest, fmt.Sprintf("不支持的模型，支持：%s", supportedStr))
		return
	}

	// 解析请求参数（仅获取需要更新的字段）
	var req dto.UpdateAIConfigRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		response.Error(c, http.StatusBadRequest, "参数错误："+err.Error())
		return
	}

	// 更新配置（非空字段才更新，避免覆盖原有配置）
	prefix := model + "_" // 环境变量前缀（如doubao_）
	if req.APIKey != "" {
		os.Setenv(prefix+"API_KEY", req.APIKey)
	}
	if req.BaseURL != "" {
		os.Setenv(prefix+"BASE_URL", req.BaseURL)
	}
	if req.ModelName != "" {
		os.Setenv(prefix+"MODEL", req.ModelName)
	}
	if req.Temperature > 0 {
		os.Setenv(prefix+"TEMPERATURE", strconv.FormatFloat(float64(req.Temperature), 'f', 1, 32))
	}
	if req.MaxTokens > 0 {
		os.Setenv(prefix+"MAX_TOKENS", strconv.Itoa(req.MaxTokens))
	}
	if req.Timeout > 0 {
		os.Setenv(prefix+"TIMEOUT", strconv.Itoa(req.Timeout))
	}

	// 返回更新后的完整配置
	GetAIConfig(c)
}
